package cn.siat.gene.service;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.net.NetUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.system.SystemUtil;
import cn.siat.gene.domain.Programme;
import cn.siat.gene.domain.SequenceOperate;
import cn.siat.gene.mapper.ProgrammeMapper;
import cn.siat.gene.mapper.SequenceOperateMapper;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.siat.common.core.domain.R;
import cn.siat.common.core.exception.ServiceException;
import cn.siat.common.core.utils.StringUtils;
import cn.siat.common.redis.service.RedisService;
import cn.siat.common.security.utils.SecurityUtils;
import cn.siat.gene.domain.DesignTBExternalPaccout;
import cn.siat.gene.mapper.DesignTBExternalPaccoutMapper;
import cn.siat.system.api.domain.SysUser;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
@Slf4j
public class DesignService {
    private final RestTemplate restTemplate;
    private final RedisService redisService;
    private final DesignTBExternalPaccoutMapper designTBExternalPaccoutMapper;
    private final ProgrammeMapper programmeMapper;
    private final SequenceOperateMapper sequenceOperateMapper;

    @Value("${url.hmzhkj-design}")
    private String designUrl;
    @Value("${url.designFile}")
    private String designFileUrl;
    @Value("${path.designFile}")
    private String designFileSavePath;
//    private String designUrl = "http://192.168.1.104:9205";

    /**
     * 获取装置设计token
     *
     * @return
     */
    public R<Map> designLogin(String username, String password) {
        MultiValueMap<String, String> loginParams = new LinkedMultiValueMap<>();
        loginParams.add("username", username);
        loginParams.add("password", password);
        R<Map> r = restTemplate.postForObject(designUrl + "/externalApi/login",
                loginParams,
                R.class);
        return r;
    }


    private HttpHeaders getHeaders() {
//        String designUserId = redisService.getCacheObject("get_design_user:" + SecurityUtils.getUserId());
//        R<Map> cache = redisService.getCacheObject("design_token:" + designUserId);
//        String token = (String) cache.getData().get("access_token");
        R<Map> designToken = getDesignToken();
        Map<String, String> data = designToken.getData();
        //创建消息头
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer " + data.get("access_token"));
        return headers;
    }

    /**
     * 装置设计中创建项目
     *
     * @param map
     * @return
     */
    public R<String> insertDesignProject(Map<String, String> map) {
        MultiValueMap<String, String> loginParams = new LinkedMultiValueMap<>();
        loginParams.add("projectName", map.get("projectName"));
        loginParams.add("projectDescription", map.get("projectDescription"));
        HttpHeaders headers = getHeaders();
        //请求实体
        HttpEntity<Map> httpEntity = new HttpEntity<>(loginParams, headers);
        R<String> r = restTemplate.exchange(designUrl + "/externalApi/insertProject",
                HttpMethod.POST,
                httpEntity,
                R.class).getBody();
        //如果token失效超时
        if (r.getCode() == 401) {
            redisService.deleteObject("get_design_user:" + SecurityUtils.getUserId());
            getDesignToken();
            headers = getHeaders();
            //请求实体
            httpEntity = new HttpEntity<>(loginParams, headers);
            r = restTemplate.exchange(designUrl + "/externalApi/insertProject",
                    HttpMethod.POST,
                    httpEntity,
                    R.class).getBody();
        }
        if (r != null) {
            String projectId = r.getData();
            Programme programme = new Programme().setId(map.get("programmeId")).setDesignProjectId(projectId);
            programmeMapper.updateById(programme);
        }

        return r;
    }

    /**
     * 创建设计
     */
    public R<String> insertDesign(Map<String, String> design) {
        String sequenceOperateId = design.get("sequenceOperateId");
        String sequenceName = design.get("sequenceName");
        String partName = design.get("partName");
        design.remove("sequenceOperateId");
        design.remove("sequenceName");
        design.remove("partName");
        HttpHeaders headers = getHeaders();
        //请求实体
        HttpEntity<Map> httpEntity = new HttpEntity<>(design, headers);
        R<String> r = restTemplate.exchange(designUrl + "/externalApi/insertDesign",
                HttpMethod.POST,
                httpEntity,
                R.class).getBody();
        //如果token失效超时
        if (r.getCode() == 401) {
            redisService.deleteObject("get_design_user:" + SecurityUtils.getUserId());
            getDesignToken();
            headers = getHeaders();
            //请求实体
            httpEntity = new HttpEntity<>(design, headers);
            r = restTemplate.exchange(designUrl + "/externalApi/insertDesign",
                    HttpMethod.POST,
                    httpEntity,
                    R.class).getBody();
        }

        //创建设计成功后插入元件
        if (r.getCode() == HttpStatus.OK.value()) {
            String designId = r.getData();
            Map map = new HashMap();
            map.put("designId", designId);
            map.put("partName", partName);
            SequenceOperate one = sequenceOperateMapper.selectById(new SequenceOperate().setId(Long.parseLong(sequenceOperateId)));
            map.put("faList", new String[]{
                    ">" + sequenceName + "\n" +
                            ("CUT".equals(one.getType()) ? one.getPreSequence() : one.getSequence())
            });
            R part = restTemplate.exchange(designUrl + "/externalApi/insertPart",
                    HttpMethod.POST,
                    new HttpEntity<>(map, headers),
                    R.class).getBody();

            //保存设计id到历史记录表
            SequenceOperate sequenceOperate = new SequenceOperate()
                    .setId(Long.parseLong(sequenceOperateId))
                    .setDesignId(designId);
            int i = sequenceOperateMapper.updateDesignById(sequenceOperate);
        }

        return r;
    }

    /**
     * 获取装置设计系统的TOKEN
     *
     * @return
     */
    public R<Map> getDesignToken() {
        //取redis中的装置设计登录token
        String designUserId = redisService.getCacheObject("get_design_user:" + SecurityUtils.getUserId());
        R<Map> cacheObject = null;
        if (StringUtils.isNotEmpty(designUserId)) {
            cacheObject = redisService.getCacheObject("design_token:" + designUserId);
        }
        //取不到就重新登陆获取token
        if (cacheObject == null) {
            //先取出绑定的装置设计账号
            QueryWrapper<DesignTBExternalPaccout> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("is_bind", 1)
                    .eq("is_delete", 1)
                    .eq("user_id", SecurityUtils.getUserId())
                    .eq("external_system_name", "装置设计系统");
            DesignTBExternalPaccout designTBExternalPaccout = designTBExternalPaccoutMapper.selectOne(queryWrapper);
            if (designTBExternalPaccout == null) {
                throw new ServiceException("当前未绑定装置设计账号!");
            }

            String username = designTBExternalPaccout.getExternalSystemUserName();
            String password = designTBExternalPaccout.getExternalSystemPassword();
            R<Map> r = designLogin(username, password);
            Map<String, Object> data = r.getData();
            SysUser sysUser = JSONObject.parseObject(data.get("userInfo").toString(), SysUser.class);
            designUserId = sysUser.getUserId();
            redisService.setCacheObject("get_design_user:" + SecurityUtils.getUserId(), designUserId, 60 * 60 * 10L, TimeUnit.SECONDS);
            redisService.setCacheObject("design_token:" + designUserId, r, 60 * 60 * 10L, TimeUnit.SECONDS);
            return r;
        }
        return cacheObject;
    }

    public String getDesignFile(String designId) {
        HttpHeaders headers = getHeaders();
        //请求实体
        HttpEntity<Map> httpEntity = new HttpEntity<>(null, headers);
        R<String> r = restTemplate.exchange(designUrl + "/externalApi/getReportNum?id=" + designId,
                HttpMethod.GET,
                httpEntity,
                R.class).getBody();
        if (r.getCode() == HttpStatus.OK.value()) {
            return r.getData();
        } else {
            throw new ServiceException(r.getMsg());
        }
    }

    public void designRevocation(String stepId, String designId) {
        HttpHeaders headers = getHeaders();
        //请求实体
        HttpEntity<Map> httpEntity = new HttpEntity<>(null, headers);
        R<String> r = restTemplate.exchange(designUrl + "/externalApi/deleteDesign?id=" + designId,
                HttpMethod.DELETE,
                httpEntity,
                R.class).getBody();
        if (r.getCode() != HttpStatus.OK.value()) {
            if (r.getMsg().indexOf("不存在") != -1) {
                sequenceOperateMapper.updateDesignById(new SequenceOperate().setId(Long.parseLong(stepId)).setDesignId(null));
            }
            throw new ServiceException(r.getMsg());
        } else {
            sequenceOperateMapper.updateDesignById(new SequenceOperate().setId(Long.parseLong(stepId)).setDesignId(null));
        }

    }

    /**
     * 打包时添加装置设计报告文件
     *
     * @param programmeId 方案id
     * @return 装置设计文件
     */
    public File[] packDesignFiles(String programmeId) {
        String designFileSavePath = null;
        if (SystemUtil.getOsInfo().isWindows()) {
            designFileSavePath = "D:" + this.designFileSavePath + "/" + programmeId + "/design/";
        } else {
            designFileSavePath = this.designFileSavePath + "/" + programmeId + "/design/";
        }
        FileUtil.del(designFileSavePath);

        List<SequenceOperate> sequenceOperates = sequenceOperateMapper.getDesignIdsByProgrammeId(programmeId);
        if(sequenceOperates == null || sequenceOperates.size() == 0){
            return null;
        }
        HttpHeaders headers = null;
        try{
            headers = getHeaders();
        }catch (ServiceException e){
            return new File[]{};
        }
//        List<File> fileList = new ArrayList<>();
        //请求实体
        HttpEntity<Map> httpEntity = new HttpEntity<>(null, headers);
        for (SequenceOperate so : sequenceOperates) {
            R<String> r = restTemplate.exchange(designUrl + "/externalApi/getReportNum?id=" + so.getDesignId(),
                    HttpMethod.GET,
                    httpEntity,
                    R.class).getBody();
            if (r.getCode() == HttpStatus.OK.value() && r.getData() != null) {
                String f = designFileSavePath + so.getSequenceName() + "_" + so.getOrder() + "_" + so.getType() + ".zip";
                File file = new File(f);
                long l = HttpUtil.downloadFile(designFileUrl + r.getData(), file);
//                if(l>0){
//                    fileList.add(file);
//                }
            }
        }

        return new File[]{new File(designFileSavePath)};
    }

    /**
     * 删除方案后,清理装置设计项目以及设计
     */
    public void clearDesign(String programmeId) {
        Programme programme = programmeMapper.selectById(programmeId);
        String designProjectId = programme.getDesignProjectId();
        HttpHeaders headers = getHeaders();
        //删除装置设计项目
        Map map = new HashMap();
        map.put("id", programme.getDesignProjectId());
        HttpEntity<Map> httpEntity = new HttpEntity<>(map, headers);
        R<String> r = restTemplate.exchange(designUrl + "/project/main/remove",
                HttpMethod.DELETE,
                httpEntity,
                R.class).getBody();
        if (r.getCode() == HttpStatus.OK.value()) {
            //循环删除相关设计
            List<SequenceOperate> sequenceOperates = sequenceOperateMapper.getDesignIdsByProgrammeId(programmeId);
            for (SequenceOperate sequenceOperate : sequenceOperates) {
                httpEntity = new HttpEntity<>(null, headers);
                restTemplate.exchange(designUrl + "/externalApi/deleteDesign?id=" + sequenceOperate.getDesignId(),
                        HttpMethod.DELETE,
                        httpEntity,
                        R.class).getBody();
            }
        } else {
            throw new ServiceException(r.getMsg());
        }

    }


}
